import random

# 使用二进制编码表示单个数字或符号
# 每个数字用8位二进制表示，0表示空，1表示火柴棍，最高位为0。
# 0 -> 01110111
# 1 -> 00100100
# 2 -> 01011101
# 3 -> 01101101
# 4 -> 00101110
# 5 -> 01101011
# 6 -> 01111011
# 7 -> 00010101
# 8 -> 01111111
# 9 -> 01101111
# 符号高4位全为1，低4位表示符号类型。
# + -> 11110000
# - -> 11110001
# = -> 11111111

# 二进制编码映射表
BINARY_ENCODING = {
    '0': 0b01110111,
    '1': 0b00100100,
    '2': 0b01011101,
    '3': 0b01101101,
    '4': 0b00101110,
    '5': 0b01101011,
    '6': 0b01111011,
    '7': 0b00010101,
    '8': 0b01111111,
    '9': 0b01101111,
    '+': 0b10000011,
    '-': 0b10000001,
    '=': 0b11111111
}

def eq_to_binary(eq):
    """
    将等式转换为二进制编码列表
    :param eq: 等式字符串 (如 "3 + 2 = 5")
    :return: 二进制编码列表
    """
    result = []
    for char in eq:
        if char == ' ':
            continue
        if char not in BINARY_ENCODING:
            raise ValueError(f"不支持的字符: {char}")
        result.append(BINARY_ENCODING[char])
    return result

def binary_to_eq(binary_list):
    """
    将二进制编码列表转换为等式字符串
    :param binary_list: 二进制编码列表
    :return: 等式字符串
    """
    result = ""
    for binary in binary_list:
        if binary == 0b01110111:
            result += '0'
        elif binary == 0b00100100:
            result += '1'
        elif binary == 0b01011011:
            result += '2'
        elif binary == 0b01101101:
            result += '3'
        elif binary == 0b00101110:
            result += '4'
        elif binary == 0b01101011:
            result += '5'
        elif binary == 0b01111011:
            result += '6'
        elif binary == 0b00010101:
            result += '7'
        elif binary == 0b01111111:
            result += '8'
        elif binary == 0b01101111:
            result += '9'
        elif binary == 0b10000011:
            result += '+'
        elif binary == 0b10000001:
            result += '-'
        elif binary == 0b11111111:
            result += '='
        else:
            raise ValueError(f"不支持的二进制编码: {binary}")
    return result

def take_away_matchestick(src_index, binary_list):
    new_binary_list = binary_list.copy()
    # 如果是等于号，则不需要拿走火柴棍
    if new_binary_list[src_index] == 0b11111111:
        print("take_away_matchestick","False", "等于号")
        return False
    # 如果来源位置是数字
    elif new_binary_list[src_index] & 0b10000000 == 0:
        # 遍历来源位置的每一位，如果是1就记录下位数，得到一个位数为1的索引列表
        bit_indexes = []
        for i in range(7):
            if new_binary_list[src_index] & (1 << i):
                bit_indexes.append(i)
        if len(bit_indexes) == 0:
            print("take_away_matchestick","False", "数字不可拿走火柴棍")
            return False
        # 随机从列表中选择一个位数为1的索引
        bit_index = random.choice(bit_indexes)
        # 拿走火柴棍
        new_binary_list[src_index] &= ~(1 << bit_index)
        binary_list[:] = new_binary_list.copy()
        print("take_away_matchestick","True", binary_list)
        return True
    # 如果来源位置是符号
    else:
        # 遍历来源位置的每一位，如果是1就记录下位数，得到一个位数为1的索引列表
        bit_indexes = []
        for i in range(2):
            if new_binary_list[src_index] & (1 << i):
                bit_indexes.append(i)
        if len(bit_indexes) == 0:
            print("take_away_matchestick","False", "符号不可拿走火柴棍")
            return False
        # 随机从列表中选择一个位数为1的索引
        bit_index = random.choice(bit_indexes)
        # 拿走火柴棍
        new_binary_list[src_index] &= ~(1 << bit_index)
        binary_list[:] = new_binary_list.copy()
        print("take_away_matchestick","True", binary_list)
        return True

def put_in_matchestick(dst_index, binary_list):
    new_binary_list = binary_list.copy()
    # 如果是等于号，则不需要拿走火柴棍
    if new_binary_list[dst_index] == 0b11111111:
        print("put_in_matchestick","False", "等于号")
        return False
    # 如果目标位置是数字
    elif new_binary_list[dst_index] & 0b10000000 == 0:
        # 遍历目标位置的每一位，如果是0就记录下位数，得到一个位数为0的索引列表
        bit_indexes = []
        for i in range(7):
            if new_binary_list[dst_index] & (1 << i) == 0:
                bit_indexes.append(i)
        if len(bit_indexes) == 0:
            print("put_in_matchestick","False", "数字不可放入火柴棍")
            return False
        # 随机从列表中选择一个位数为0的索引
        bit_index = random.choice(bit_indexes)
        # 放入火柴棍
        new_binary_list[dst_index] |= (1 << bit_index)
        binary_list[:] = new_binary_list.copy()
        print("put_in_matchestick","True", binary_list)
        return True
    # 如果目标位置是符号
    else:
        # 遍历目标位置的每一位，如果是0就记录下位数，得到一个位数为0的索引列表
        bit_indexes = []
        for i in range(2):
            if new_binary_list[dst_index] & (1 << i) == 0:
                bit_indexes.append(i)
        if len(bit_indexes) == 0:
            print("put_in_matchestick","False", "符号不可放入火柴棍")
            return False
        # 随机从列表中选择一个位数为0的索引
        bit_index = random.choice(bit_indexes)
        # 放入火柴棍
        new_binary_list[dst_index] |= (1 << bit_index)
        binary_list[:] = new_binary_list.copy()
        print("put_in_matchestick","True", binary_list)
        return True

def random_move_matchstick_once(binary_list):
    """
    随机移动火柴棍一次
    :param binary_list: 二进制编码列表
    :return: 移动后的二进制编码列表
    """
    new_binary_list = binary_list.copy()
    # 遍历binary_list，如果不是等号则记录下索引，得到一个索引列表
    index_list = []
    for i in range(len(new_binary_list)):
        if not (new_binary_list[i] == 0b11111111):
            index_list.append(i)
    # 随机选择一个来源位置
    src_index = random.choice(index_list)
    # 从index_list中去除src_index
    index_list.remove(src_index)
    # 随机选择一个目标位置
    dst_index = random.choice(index_list)

    # 从来源位置拿走一根火柴棍
    rs = take_away_matchestick(src_index, new_binary_list)
    if not rs:
        return False
    # 往目标位置方一根火柴棍
    rs = put_in_matchestick(dst_index, new_binary_list)
    if not rs:
        return False

    binary_list[:] = new_binary_list.copy()
    return True

def random_move_matchstick(moves, binary_list):
    for i in range(moves):
        # 尝试1000次随机移动1根火柴棍
        for j in range(1000):
            new_binary_list = binary_list.copy()
            rs = random_move_matchstick_once(new_binary_list)
            if rs:
                return new_binary_list
    return []

def generate_answer_equation():
    """
    随机生成有效的数学等式（答案）
    :return: 数学上成立的等式字符串
    """
    operations = ['+', '-']
    op = random.choice(operations)

    if op == '+':
        # 生成加法等式 a + b = c (确保a+b≤9)
        c = random.randint(0, 9)
        a = random.randint(0, c)
        b = c - a
    else:
        # 生成减法等式 a - b = c (确保a≥b)
        a = random.randint(0, 9)
        b = random.randint(0, a)
        c = a - b

    return f"{a} {op} {b} = {c}"

def move_matchstick(moves, answer_eq):
    binary_list = eq_to_binary(answer_eq)
    for i in range(1000):
        print(answer_eq)
        answer_binary_list = random_move_matchstick(moves, binary_list)
        if len(answer_binary_list) == 0:
            print("无法生成有效的题目")
            continues
        try:
            question_eq = binary_to_eq(answer_binary_list)
            return question_eq
        except ValueError:
            print("生成的答案不符合要求，请重新生成")
            print("")
    return ""

def main():
    print("火柴数学题生成器框架")
    try:
        moves = int(input("请输入需要移动的火柴棍数量: "))
        if moves <= 0:
            print("移动数量必须大于0")
            return

    except ValueError:
        print("请输入有效的数字")
        return

    answer_eq = generate_answer_equation()
    question_eq = move_matchstick(moves, answer_eq)
    print("题目:", question_eq)
    print("答案:", answer_eq)

if __name__ == "__main__":
    main()
